// import TIM from "tim-wx-sdk";
import TIM from "./tim-wx-sdk/tim-wx.js"
import TIMUploadPlugin from "tim-upload-plugin";
import { useImStoreWithOut } from '@/store/modules/im';
import { useUserStoreWithOut } from '@/store/modules/user';
const useIm = useImStoreWithOut();

import { CacheEnum } from '@/enums/cacheEnum';
import { useEnv } from '@/hooks/core/useEnv';
const { isTestEnv } = useEnv();
const env = import.meta.env;
import { LogLevel } from './enums';

class Tim {
    private SDKAppID: string | number
    public $TUIKit: any
    public $TIM: any
    public currentStore: any = {}

    constructor() {
        this.SDKAppID = isTestEnv() ? env['UNIAPP_DEVELOP_IM_SDKAPPID'] : env['UNIAPP_RELEASE_IM_SDKAPPID'] ;
        this.$TUIKit = TIM.create({ SDKAppID: Number(this.SDKAppID) });
        this.$TIM = TIM;
        // 注册文件上传插件
        // #ifdef MP-WEIXIN || H5
        this.$TUIKit.registerPlugin({ "tim-upload-plugin": TIMUploadPlugin });
        this.$TUIKit.setLogLevel(LogLevel.ERROR);
        // #endif
        this.bindTIMEvent();
        if (useIm.isSDKReady) {
            this.getConversationList();
        }
    }


    /** IM登录 */
    public async imLogin() {
        return new Promise<void>(async (resolve, reject) => {
            const userInfo = uni.getStorageSync(CacheEnum.userInfo);
            const params = {
                userID: userInfo.imUserId,
                userSig: userInfo.userSig
            }
            if(!params.userID || !params.userSig){
                reject('用户未登录')
            }else if(useIm.isLogin){
                resolve()
            }else{
                const { code } = await this.$TUIKit.login(params).catch((err:any)=>{reject(err)})
                useIm.isLogin = code === 0
                resolve()
            }
        })
    }

    /*
   * 获取消息列表
   * @returns {Promise}
   */
    public async getConversationList() {
        return new Promise<void>(async (resolve, reject) => {
            try {
                const imResponse = await this.$TUIKit.getConversationList();
                useIm.setImConversationList(imResponse.data.conversationList);
                uni.hideLoading();
                resolve(imResponse);
            } catch (error) {
                reject(error);
            }
        })
    }
    /**
   * 设置已读
   *
   * @param {string} conversationID 会话ID
   * @returns {Promise}
   */
    public async setMessageRead(conversationID: string) {
        return new Promise<void>(async (resolve, reject) => {
            try {
                const imResponse: any = await this.$TUIKit.setMessageRead({
                    conversationID,
                });
                resolve(imResponse);
            } catch (error) {
                reject(error);
            }
        });
    }

    // sdk ready 以后可调用 API
    private handleSDKReady(event: any) {
        useIm.isSDKReady = true
        console.log(useIm.isSDKReady, '初始化完成');
        // tim.createGroup('前端测试群006',[{userID: 'IM_1001_20'},{userID: 'IM_1001_1'}])
    }
    private handleSDKNotReady(event: any) {
        console.log('SDK 未完成初始化');
    }
    private handleKickedOut(event: any) {
        useIm.isLogin = false;
        useUserStoreWithOut().resetApp();
        uni.showToast({
            title: `${this.kickedOutReason(event.data.type)}被踢出。`,
            icon: "none",
        });
    }
    private kickedOutReason(type: any) {
        switch (type) {
            case this.$TIM.TYPES.KICKED_OUT_MULT_ACCOUNT:
                return "多实例登录";
            case this.$TIM.TYPES.KICKED_OUT_MULT_DEVICE:
                return "多设备登录";
            case this.$TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED:
                return "userSig 过期";
            case this.$TIM.TYPES.KICKED_OUT_REST_API:
                return "REST API kick 接口踢出";
            default:
                return "";
        }
    }
    private handleMessageReceived(event: any) {
        console.log(event, '接收到新消息');
        event.data.forEach((item: any) => {
            if (item.conversationID === useIm.conversation.conversationID) {
                const messageList = [...useIm.messageList, item];
                // 更新 messageList
                useIm.messageList = messageList;
            }
        });
    }
    private handleConversationListUpdate(res: any) {
        console.log(res, '会话列表更新');
        useIm.setImConversationList(res.data);
        wx.hideLoading();
    }

    private unreadMessageCountUpdated(res: any) {
        useIm.unreadTotal = res.data
        console.log(useIm.unreadTotal,'未读消息数');
    }

    /** TIM 事件监听注册接口 */
    public bindTIMEvent() {
        // 收到离线消息和会话列表同步完毕通知，接入侧可以调用 sendMessage 等需要鉴权的接口
        this.$TUIKit.on(this.$TIM.EVENT.SDK_READY, this.handleSDKReady);
        // 收到 SDK 进入 not ready 状态通知，此时 SDK 无法正常工作
        this.$TUIKit.on(this.$TIM.EVENT.SDK_NOT_READY, this.handleSDKNotReady);
        // 收到被踢下线通知
        this.$TUIKit.on(this.$TIM.EVENT.KICKED_OUT, this.handleKickedOut);
        // 收到推送的单聊、群聊、群提示、群系统通知的新消息，可通过遍历 event.data 获取消息列表数据并渲染到页面
        this.$TUIKit.on(this.$TIM.EVENT.MESSAGE_RECEIVED, this.handleMessageReceived);
        // 收到会话列表更新通知，可通过遍历 event.data 获取会话列表数据并渲染到页面
        this.$TUIKit.on(this.$TIM.EVENT.CONVERSATION_LIST_UPDATED, this.handleConversationListUpdate);
        // 会话未读总数更新
        this.$TUIKit.on(TIM.EVENT.TOTAL_UNREAD_MESSAGE_COUNT_UPDATED, this.unreadMessageCountUpdated);
    }

    /**
     * 获取 messageList
     *
     * @param {any} options 获取 messageList 参数
     * @param {Boolean} history  是否获取历史消息
     * @returns {Promise}
     */
    public async getMessageList(options: any, history?: Boolean) {
        return new Promise<any[]>(async (resolve, reject) => {
            try {
                const imResponse = await this.$TUIKit.getMessageList(options);
                let messageList;
                if (!history) {
                    messageList = imResponse.data.messageList;
                } else {
                    messageList = [
                        ...imResponse.data.messageList,
                        ...useIm.messageList,
                    ];
                }
                this.currentStore.nextReqMessageID = imResponse.data.nextReqMessageID;
                this.currentStore.isCompleted = imResponse.data.isCompleted;
                useIm.messageList = messageList
                console.log(useIm.messageList,'聊天消息');
                resolve(imResponse.data);
            } catch (error) {
                reject(error);
            }
        });
    }
    /**
     * 数据监听回调
     *
     * @param {any} newValue 新数据
     * @param {any} oldValue 旧数据
     *
     */
    public updateStore() {
        this.getMessageList({
            conversationID: useIm.conversation.conversationID,
            count: 15,
        });
        useIm.messageList = [];
    }

    /**
     * 获取历史消息
     *
     * @returns {Promise}
     */
    public async getHistoryMessageList() {
        return new Promise<any[]>(async (resolve, reject) => {
            try {
                const options = {
                    conversationID: useIm.conversation.conversationID,
                    nextReqMessageID: this.currentStore.nextReqMessageID,
                    count: 15,
                };
                let messageList = [];
                if (!this.currentStore.isCompleted) {
                    messageList = await this.getMessageList(options, true);
                }
                resolve(messageList);
            } catch (error) {
                reject(error);
            }
        });
    }

    /**
   * 创建消息生成参数
   *
   * @param {Object} content 消息体
   * @param {String} type 消息类型 text: 文本类型 file: 文件类型 face: 表情 location: 地址 custom: 自定义 merger: 合并 forward: 转发
   * @param {Callback} callback 回调函数
   * @param {any} to 发送的对象
   * @returns {options} 消息参数
   */
    public handleMessageOptions(
        content: any,
        type: string,
        callback?: any,
        to?: any
    ) {
        const options: any = {
            to: "",
            conversationType: to?.type || useIm.conversation.type,
            payload: content,
            needReadReceipt: true,
        };
        if (type === "file" && callback) {
            options.onProgress = callback;
        }
        switch (options.conversationType) {
            case this.$TIM.TYPES.CONV_C2C:
                options.to =
                    to?.userProfile?.userID ||
                    useIm.conversation?.userProfile?.userID ||
                    "";
                break;
            case this.$TIM.TYPES.CONV_GROUP:
                options.to =
                    to?.groupProfile?.groupID ||
                    useIm.conversation?.groupProfile?.groupID ||
                    "";
                break;
            default:
                break;
        }
        return options;
    }
    /**
     * 发送文本消息
     *
     * @param {any} text 发送的消息
     * @returns {Promise}
     */
    public sendTextMessage(text: any): Promise<any> {
        return new Promise<void>(async (resolve, reject) => {
            try {
                const options = this.handleMessageOptions({ text }, "text");
                const message = this.$TUIKit.createTextMessage(options);
                // 优化写法
                const messageList = [...useIm.messageList, message];
                useIm.messageList = messageList
                const imResponse = await this.$TUIKit.sendMessage(message);
                useIm.messageList = useIm.messageList.map((item: any) => {
                    if (item.ID === imResponse.data.message.ID) {
                        return imResponse.data.message;
                    }
                    return item;
                });
                resolve(imResponse);
            } catch (error) {
                reject(error);
                const middleData = useIm.messageList;
                useIm.messageList = middleData
            }
        });
    }

    /**
     * 发送表情消息
     *
     * @param {Object} data 消息内容
     * @param {Number} data.index 表情索引
     * @param {String} data.data 额外数据
     * @returns {Promise}
     */
    public sendFaceMessage(data: any): Promise<any> {
        return new Promise<void>(async (resolve, reject) => {
            try {
                const options = this.handleMessageOptions(data, "face");
                const message = this.$TUIKit.createFaceMessage(options);
                // useIm.messageList.push(message);
                // 优化写法
                const messageList = [...useIm.messageList, message];
                useIm.messageList = messageList
                const imResponse = await this.$TUIKit.sendMessage(message);
                useIm.messageList = useIm.messageList.map((item: any) => {
                    if (item.ID === imResponse.data.message.ID) {
                        return imResponse.data.message;
                    }
                    return item;
                });
                resolve(imResponse);
            } catch (error) {
                reject(error);
            }
        });
    }
    /**
   * 文件上传进度函数处理
   *
   * @param {number} progress 文件上传进度 1表示完成
   * @param {message} message 文件消息
   */
    public handleUploadProgress(progress: number, message: any) {
        useIm.messageList.map((item: any) => {
            if (item.ID === message.ID) {
                item.progress = progress;
            }
            return item;
        });
    }
    /**
     * 发送语音消息
     *
     * @param {audio} audio 音频文件
     * @returns {Promise}
     */
    public sendAudioMessage(audio: any): Promise<any> {
        return new Promise<void>(async (resolve, reject) => {
            try {
                const options = this.handleMessageOptions(
                    { file: audio },
                    "file",
                    (progress: number) => {
                        this.handleUploadProgress(progress, message);
                    }
                );
                const message = this.$TUIKit.createAudioMessage(options);
                // todo  上屏图片消息在发送之前没有尺寸，待优化
                const messageList = [...useIm.messageList, message];
                useIm.messageList = messageList
                const imResponse = await this.$TUIKit.sendMessage(message);
                console.log("发送音频消息完成", imResponse);
                useIm.messageList = useIm.messageList.map((item: any) => {
                    if (item.ID === imResponse.data.message.ID) {
                        return imResponse.data.message;
                    }
                    return item;
                });
                resolve(imResponse);
            } catch (error) {
                reject(error);
            }
        });
    }
    /**
     * 发送视频消息
     *
     * @param {Video} video 图片文件
     * @returns {Promise}
     */
    public sendVideoMessage(res: any): Promise<any> {
        return new Promise<void>(async (resolve, reject) => {
            try {
                const options = this.handleMessageOptions({ file: res }, "file");
                const message = this.$TUIKit.createVideoMessage(options);
                // todo  上屏图片消息在发送之前没有尺寸，本地获取补充
                // message.payload.imageInfoArray[1].height = video.height
                // message.payload.imageInfoArray[1].width = video.width
                const messageList = [...useIm.messageList, message];
                useIm.messageList = messageList
                const imResponse = await this.$TUIKit.sendMessage(message);
                useIm.messageList = useIm.messageList.map((item: any) => {
                    if (item.ID === imResponse.data.message.ID) {
                        return imResponse.data.message;
                    }
                    return item;
                });
                resolve(imResponse);
            } catch (error) {
                reject(error);
            }
        });
    }

    /**
     * 发送图片消息
     *
     * @param {res} res 图片文件
     * @param {image} 图片尺寸
     * @returns {Promise}
     */
    public sendImageMessage(res: any, image: any): Promise<any> {
        return new Promise<void>(async (resolve, reject) => {
            try {
                const options = this.handleMessageOptions({ file: res }, "file");
                const message = this.$TUIKit.createImageMessage(options);
                // todo  上屏图片消息在发送之前没有尺寸，本地获取补充
                message.payload.imageInfoArray[1].height = image.height;
                message.payload.imageInfoArray[1].width = image.width;
                const messageList = [...useIm.messageList, message];
                useIm.messageList = messageList
                const imResponse = await this.$TUIKit.sendMessage(message);
                useIm.messageList = useIm.messageList.map((item: any) => {
                    if (item.ID === imResponse.data.message.ID) {
                        return imResponse.data.message;
                    }
                    return item;
                });
                resolve(imResponse);
            } catch (error) {
                reject(error);
            }
        });
    }

    /**
     * 创建群聊
     *
     * @param {groupName}  群名称
     * @param {groupUserList} 成员列表 [{userID: '310'}]
     * @returns {Promise}
     */
    public createGroup(groupName: string,groupUserList: any): Promise<any> {
        return new Promise<void>(async (resolve, reject) => {
            try {
                const options = {
                    type: this.$TIM.TYPES.GRP_MEETING, // 群类型
                    name: groupName, // 群名称
                    memberList: groupUserList // 成员列表
                }
                const response = this.$TUIKit.createGroup(options);
                resolve(response);
            } catch (error) {
                reject(error);
            }
        });
    }
}

const tim = new Tim();
export default tim;